home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 1
/
Nebula One.iso
/
Mail
/
pine3.92
/
pico
/
os_win.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-03-14
|
18KB
|
865 lines
#line 2 "os_win.c" /* So compiler knows original name of this file.*/
/*
* $Id: os_win.c,v 4.32 1996/03/15 07:41:11 hubert Exp $
*
* Program: Operating system dependent routines - MS Windows 3.1
*
*
* Tom Unger
* Networks and Distributed Computing
* Computing and Communications
* University of Washington
* Administration Builiding, AG-44
* Seattle, Washington, 98195, USA
* Internet: mikes@cac.washington.edu
*
* Please address all bugs and comments to "pine-bugs@cac.washington.edu"
*
*
* Pine and Pico are registered trademarks of the University of Washington.
* No commercial use of these trademarks may be made without prior written
* permission of the University of Washington.
*
* Pine, Pico, and Pilot software and its included text are Copyright
* 1989-1996 by the University of Washington.
*
* The full text of our legal notices is contained in the file called
* CPYRIGHT, included with this distribution.
*
*
* Notes:
* - mouse support added (mss, 921215)
*
* Portions of this code derived from MicroEMACS 3.10:
*
* MSDOS.C: Operating specific I/O and Spawning functions
* under the MS/PCDOS operating system
* for MicroEMACS 3.10
* (C)opyright 1988 by Daniel M. Lawrence
*
*/
/*#include <windows.h>*/
#include <stdio.h>
#include <errno.h>
#include <setjmp.h>
#include <time.h>
#include <fcntl.h>
/*#include <io.h>*/
/*#include <bios.h>*/
#include "osdep.h"
#include "pico.h"
#include "estruct.h"
#include "efunc.h"
#include "edef.h"
#include "pico.h"
#include "dos_gen.h"
#ifdef MOUSE
#define MOUSE_BUTTONS 3
#endif /* MOUSE */
/*
* Internal functions...
*/
int timeout = 0;
static int MapMSKEYtoPK (int c);
static int ProcessMouse(MEvent *, unsigned int *);
int ttopen ();
int ttclose ();
/*
* Include generic DOS/Windows routines
*/
#include "dos_gen.c"
#define MARGIN 8 /* size of minimim margin and */
#define SCRSIZ 64 /* scroll size for extended lines */
#define MROW 2 /* rows in menu */
/*
* Standard terminal interface dispatch table. Fields point to functions
* that operate the terminal. All these functions live in mswin.c, but
* this structure is defined here because it is specific to pico.
*/
TERM term = {
0,
0,
MARGIN,
SCRSIZ,
MROW,
ttopen,
ttclose,
mswin_getc,
mswin_putc,
mswin_flush,
mswin_move,
mswin_eeol,
mswin_eeop,
mswin_beep,
mswin_rev
};
/*
* mswin_resize - windows specific callback to set pico's internal tables
* to new screen dimensions.
*/
int
mswin_resize (row, col)
int row, col;
{
resize_pico (row-1, col);
return (0);
}
/*
* ttresize - recompute the screen dimensions if necessary, and then
* adjust pico's internal buffers accordingly.
*/
int ttresize ()
{
int row, col;
mswin_getscreensize(&row, &col);
resize_pico (row-1, col);
}
/*
* This function is called once to set up the terminal device streams.
*/
int
ttopen()
{
int rows, columns;
mswin_getscreensize (&rows, &columns);
term.t_nrow = rows - 1;
term.t_ncol = columns;
term.t_scrsiz = (columns * 2) / 3;
/*
* Do we implement optimized character insertion and deletion?
* o_insert() and o_delete()
*/
inschar = delchar = FALSE;
revexist = TRUE;
mswin_setresizecallback (mswin_resize);
#if MOUSE
init_mouse();
#else /* !MOUSE */
mexist = 0;
#endif /* MOUSE */
return(1);
}
#ifdef MOUSE
/*
* init_mouse - check for and initialize mouse driver...
*/
int
init_mouse()
{
nbuttons = MOUSE_BUTTONS;
return (mexist = TRUE); /* Mouse always exists under windows */
}
/*
* mouseon - call made available for programs calling pico to turn ON the
* mouse cursor.
*/
void
mouseon()
{
}
/*
* mouseoff - call made available for programs calling pico to turn OFF the
* mouse cursor.
*/
void
mouseoff()
{
}
#endif
/*
* This function gets called just before we go back home to the command
* interpreter.
*/
int
ttclose()
{
mswin_clearresizecallback (mswin_resize);
return(1);
}
/*
* Flush terminal buffer. Does real work where the terminal output is buffered
* up. A no-operation on systems where byte at a time terminal I/O is done.
*/
int
ttflush()
{
return(1);
}
/*
* Read in a key.
* Do the standard keyboard preprocessing. Convert the keys to the internal
* character set. Resolves escape sequences and returns no-op if global
* timeout value exceeded.
*/
int
GetKey ()
{
int ch = 0;
unsigned int lch;
long timein;
MEvent mouse;
ch = NODATA;
timein = time(0L);
/*
* Main character processing loop.
*/
while((ch = mswin_getc ()) == MSWIN_KEY_NODATA) {
#if MOUSE
/* Check Mouse. If we get a mouse event, convert to char
* event and return that. */
if (checkmouse (&ch,0,0,0)) {
curwp->w_flag |= WFHARD;
return (ch);
}
#endif /* MOUSE */
/* Check Timeout. */
if(time(0L) >= timein+timeout)
return(NODATA);
}
return (MapMSKEYtoPK (ch));
}
static int
MapMSKEYtoPK (int c)
{
switch (c) {
case MSWIN_KEY_UP: return (K_PAD_UP);
case MSWIN_KEY_DOWN: return (K_PAD_DOWN);
case MSWIN_KEY_RIGHT: return (K_PAD_RIGHT);
case MSWIN_KEY_LEFT: return (K_PAD_LEFT);
case MSWIN_KEY_SCROLLUPPAGE:
case MSWIN_KEY_PREVPAGE: return (K_PAD_PREVPAGE);
case MSWIN_KEY_SCROLLDOWNPAGE:
case MSWIN_KEY_NEXTPAGE: return (K_PAD_NEXTPAGE);
case MSWIN_KEY_HOME: return (K_PAD_HOME);
case MSWIN_KEY_END: return (K_PAD_END);
case MSWIN_KEY_DELETE: return (K_PAD_DELETE);
case MSWIN_KEY_F1: return (F1);
case MSWIN_KEY_F2: return (F2);
case MSWIN_KEY_F3: return (F3);
case MSWIN_KEY_F4: return (F4);
case MSWIN_KEY_F5: return (F5);
case MSWIN_KEY_F6: return (F6);
case MSWIN_KEY_F7: return (F7);
case MSWIN_KEY_F8: return (F8);
case MSWIN_KEY_F9: return (F9);
case MSWIN_KEY_F10: return (F10);
case MSWIN_KEY_F11: return (F11);
case MSWIN_KEY_F12: return (F12);
case MSWIN_KEY_SCROLLUPLINE: return (K_SCROLLUPLINE);
case MSWIN_KEY_SCROLLDOWNLINE: return (K_SCROLLDOWNLINE);
case MSWIN_KEY_SCROLLTO: return (K_SCROLLTO);
case MSWIN_KEY_NODATA: return (NODATA);
}
/* Control keys. */
if (c < ' ')
return (CTRL | (c + '@'));
/* Normal keys. */
return (c);
}
#if MOUSE
/*
* checkmouse - Check mouse and return maped command.
*
* EXPORTED to pico.
* NOTE: "down", "xxx", and "yyy" aren't used under windows.
*/
int
checkmouse (unsigned int *ch, int ddd, int xxx, int yyy)
{
static int oindex; /* Index of previous mouse down. */
int k; /* current bit/button of mouse */
int mcol; /* current mouse column */
int mrow; /* current mouse row */
int down; /* TRUE when mouse down event. */
unsigned long r;
int rv = 0; /* TRUE when we have something to return. */
MEvent mouse;
int i = 0;
MENUITEM *mp;
*ch = 0;
/* Mouse installed? */
if (!mexist)
return (FALSE);
if (!mswin_getmouseevent (&mouse))
return (FALSE);
/* Location of mouse event. */
mcol = mouse.nColumn;
mrow = mouse.nRow;
/*
* If there is a tracking function it gets all the mouse events
* reguardless of where they occur.
*/
if (mtrack != NULL) {
r = mtrack (mouse.event, mrow, mcol, mouse.button, mouse.keys);
if (r & 0xffff){
*ch = (unsigned) ((r>>16) & 0xffff);
rv = TRUE;
}
return (rv);
}
/* Mouse down or up? */
if (mouse.event == M_EVENT_DOWN) { /* button down */
oindex = -1; /* No Previous mouse down. */
}
/* In special screen region? */
for(mp = mfunc; mp; mp = mp->next)
if(mp->action && M_ACTIVE(mrow, mcol, mp))
break;
if(mp){
r = (*mp->action)(mouse.event, mrow, mcol, mouse.button, mouse.keys);
if (r & 0xffff){
*ch = (unsigned) ((r>>16) & 0xffff);
rv = TRUE;
}
}
else{
/* In any of the menuitems? */
while(1){ /* see if we understand event */
if(i >= 12){
i = -1; /* Not Found. */
break;
}
if(M_ACTIVE(mrow, mcol, &menuitems[i]))
break; /* Found. */
i++; /* Next. */
}
/* Now, was that a mouse down or mouse up? */
if (mouse.event == M_EVENT_DOWN) { /* button down */
oindex = i; /* remember where */
if(i != -1) /* invert label */
invert_label (1, &menuitems[i]);
}
else if (mouse.event == M_EVENT_UP) {/* button up */
if (oindex != -1) { /* If up in menu item. */
if (i == oindex){ /* And same item down in. */
*ch = menuitems[i].val; /* Return menu character. */
rv = 1;
}
}
}
}
/* If this is mouse up AND there was a mouse down in a menu item
* then uninvert that menu item */
if(mouse.event == M_EVENT_UP && oindex != -1)
invert_label(0, &menuitems[oindex]); /* restore label */
return(rv);
}
/*
* invert_label - highlight the label of the given menu item.
*/
void
invert_label(state, m)
int state;
MENUITEM *m;
{
int i, j, r, c, p;
char *lp;
int old_state;
int wasShown;
int col_offset;
if(m->val == mnoop)
return;
mswin_getpos (&r, &c); /* get cursor position */
wasShown = mswin_showcursor (0);
old_state = mswin_getrevstate ();
/*
* Leave the command name bold
*/
col_offset = (state || !(lp=strchr(m->label, ' '))) ? 0 : (lp - m->label);
(*term.t_move)(m->tl.r, m->tl.c + col_offset);
(*term.t_rev)(state);
for(i = m->tl.r; i <= m->br.r; i++) {
for(j = m->tl.c + col_offset; j <= m->br.c; j++) {
if(i == m->lbl.r && j == m->lbl.c + col_offset){ /* show label?? */
lp = m->label + col_offset;
while(*lp && j++ < m->br.c)
(*term.t_putchar)(*lp++);
continue;
}
else
(*term.t_putchar)(' ');
}
}
(*term.t_rev)(old_state);
mswin_move (r, c);
mswin_showcursor (wasShown);
}
#endif /* MOUSE */
/*
* Called by mswin to scroll text in window in responce to the scrollbar.
*
* Args: cmd - what type of scroll operation.
* scroll_pos - paramter for operation.
* used as position for SCROLL_TO operation.
*
* Returns: TRUE - did the scroll operation.
* FALSE - was not able to do the scroll operation.
*/
int
pico_scroll_callback (cmd, scroll_pos)
int cmd;
long scroll_pos;
{
switch (cmd) {
case MSWIN_KEY_SCROLLUPLINE:
scrollupline (0, 1);
break;
case MSWIN_KEY_SCROLLDOWNLINE:
scrolldownline (0, 1);
break;
case MSWIN_KEY_SCROLLUPPAGE:
backpage (0, 1);
break;
case MSWIN_KEY_SCROLLDOWNPAGE:
forwpage (0, 1);
break;
case MSWIN_KEY_SCROLLTO:
scrollto (0, 0);
break;
}
update ();
return (TRUE);
}
/*
* Update the scroll range and position. (exported)
*
* This is where curbp->b_linecnt is really managed. With out this function
* to count the number of lines when needed curbp->b_linecnt will never
* really be correct. BUT, this function is only compiled into the
* windows version, so b_linecnt will only ever be right in the windows
* version. OK for now because that is the only version that
* looks at b_linecnt.
*/
update_scroll ()
{
long scr_pos;
long scr_range;
LINE *lp;
static LINE *last_top_line = NULL;
static long last_scroll_pos = -1;
if (ComposerEditing) {
/* Editing header - don't allow scroll bars. */
mswin_setscrollrange (0);
return(0);
}
/*
* Count the number of lines in the current bufer. Done when:
*
* when told to recount: curbp->b_linecnt == -1
* when the top line changed: curwp->w_linep != last_top_line
* when we don't know the scroll pos: last_scroll_pos == -1
*
* The first line in the list is a "place holder" line and is not
* counted. The list is circular, when we return the to place
* holder we have reached the end.
*/
if(curbp->b_linecnt == -1 || curwp->w_linep != last_top_line
|| last_scroll_pos == -1) {
scr_range = 0;
scr_pos = 0;
for (lp = lforw (curbp->b_linep); lp != curbp->b_linep;
lp = lforw (lp)) {
if (lp == curwp->w_linep)
scr_pos = scr_range;
++scr_range;
}
curbp->b_linecnt = scr_range;
last_scroll_pos = scr_pos;
last_top_line = curwp->w_linep;
}
/*
* Set new scroll range and position.
*/
mswin_setscrollrange (curbp->b_linecnt - 1);
mswin_setscrollpos (last_scroll_pos);
return (0);
}
/*
* alt_editor - fork off an alternate editor for mail message composition
*
*/
int
alt_editor(int f, int n)
{
char eb[NLINE]; /* buf holding edit command */
char *fn; /* tmp holder for file name */
char errbuf[128];
char *writetmp();
int status;
int done;
int rc;
if(Pmaster == NULL)
return(-1);
if(gmode&MDSCUR){
emlwrite("Alternate editor not available in restricted mode", NULL);
return(-1);
}
if(Pmaster->alt_ed == NULL){
if(!(gmode&MDADVN)){
emlwrite("\007Unknown Command",NULL);
return(-1);
}
/* Guess which editor they want. */
if(getenv("EDITOR"))
strcpy(eb, (char *)getenv("EDITOR"));
else
*eb = '\0';
done = FALSE;
while(!done){
rc = mlreplyd("Which alternate editor ? ",eb,NLINE,QDEFLT,NULL);
switch(rc){
case ABORT:
return(-1);
case HELPCH:
emlwrite("no alternate editor help yet", NULL);
/* take sleep and break out after there's help */
sleep(3);
break;
case (CTRL|'L'):
sgarbf = TRUE;
update();
break;
case TRUE:
case FALSE: /* does editor exist ? */
if(*eb == '\0'){ /* leave silently? */
mlerase();
return(-1);
}
done++;
break;
default:
break;
}
}
}
else
strcpy(eb, Pmaster->alt_ed);
if((fn=writetmp(0, 1)) == NULL){ /* get temp file */
emlwrite("Problem writing temp file for alt editor", NULL);
return(-1);
}
strcat(eb, " ");
strcat(eb, fn);
emlwrite("Waiting for alternate editor to finish...", NULL);
status = mswin_exec_and_wait ("alternate editor", eb);
switch (status) {
case 0:
/*
* Success: replace edited text with new text
*/
curbp->b_flag &= ~BFCHG; /* make sure old text gets blasted */
readin(fn, 0); /* read new text overwriting old */
unlink(fn); /* blast temp file */
curbp->b_flag |= BFCHG; /* mark dirty for packbuf() */
ttopen(); /* reset the signals */
refresh(0, 1); /* redraw */
return(0);
/*
* Possible errors.
*/
case -1:
/* Failed to map return from WinExec to a HTASK. */
emlwrite("Problem finding alternet editor task handle.", NULL);
return (-1);
case -2:
/* User decided to abandon the alternate editor.*/
emlwrite("Alternate editor abandoned.", NULL);
return (-1);
default:
mswin_exec_err_msg ("alternate editor", status, errbuf, 128);
emlwrite (errbuf, NULL);
return (-1);
}
return (-1);
}
/*
*
*/
void
pico_config_menu_items (KEYMENU *keymenu)
{
int i;
KEYMENU *k;
int key;
char cleanLabel[64];
char *rb;
mswin_menuitemclear ();
/* keymenu's seem to be hardcoded at 12 entries. */
for (i = 0, k = keymenu; i < 12; ++i, ++k) {
if (k->name != NULL && k->label != NULL &&
k->menuitem != KS_NONE) {
if (k->name[0] == '^')
key = CTRL | k->name[1];
else if (strcmp(k->name, "Ret") == 0)
key = '\r';
else
key = k->name[0];
if (k->label[0] == '[' && strchr (k->label, ']') != NULL) {
strcpy (cleanLabel, &k->label[1]);
rb = strchr (cleanLabel, ']');
*rb = '\0';
mswin_menuitemadd (key, cleanLabel, k->menuitem, 0);
}
else
mswin_menuitemadd (key, k->label, k->menuitem, 0);
}
}
}
/*
* bktoshell - suspend and wait to be woken up
*
* NOTE: Not yet used under WINDOWS.
*/
int
bktoshell()
{
return (0);
}
/*
* P_open - run the given command in a sub-shell returning a file pointer
* from which to read the output
*
* note:
* For OS's other than unix, you will have to rewrite this function.
* Hopefully it'll be easy to exec the command into a temporary file,
* and return a file pointer to that opened file or something.
*
* xxx Need to figure out how to do this in windows.
*/
FILE *P_open(c)
char *c;
{
return (NULL);
}
/*
* P_close - close the given descriptor
*
*/
P_close(fp)
FILE *fp;
{
}
/*
* pico_file_browse - Exported version of FileBrowse below.
*/
pico_file_browse(pdata, dir, fn, sz, flags)
PICO *pdata;
char *dir, *fn, *sz;
int flags;
{
return(FileBrowse(dir, fn, sz, flags));
}
/*
* FileBrowse - display contents of given directory dir
*
* intput:
* dir points to initial dir to browse.
* fn initial file name.
* flags
*
* returns:
* dir points to currently selected directory (without
* trailing seperator character).
* fn points to currently selected file
* sz points to size of file if ptr passed was non-NULL
*
* 1 if a file's been selected
* 0 if no files seleted
* -1 if there where problems
*/
FileBrowse(dir, fn, sz, flags)
char *dir, *fn, *sz; /* dir, name and optional size */
int flags;
{
struct stat sbuf;
int rc;
char lfn[NFILEN];
if (flags & FB_SAVE) {
rc = mswin_savefile (dir, fn, NFILEN);
}
else {
*fn = '\0'; /* No initial file names for
* open. */
rc = mswin_openfile (dir, fn, NFILEN);
}
if (rc == 0) {
if (sz != NULL) {
/* build full path to stat file. */
strcpy (lfn, dir);
strcat (lfn, S_FILESEP);
strcat (lfn, fn);
if (stat (fn, &sbuf) < 0)
strcpy (sz, "0");
else
strcpy (sz, prettysz (sbuf.st_size));
}
return (1);
}
return (0);
}
ResizeBrowser ()
{
return (0);
}